home *** CD-ROM | disk | FTP | other *** search
/ Aminet 30 / Aminet 30 (1999)(Schatztruhe)[!][Apr 1999].iso / Aminet / gfx / misc / gnuplot-3.7src.lha / gnuplot-3.7src / gnuplot-3.7.lha / gnuplot-3.7 / os2 / gclient.c < prev    next >
C/C++ Source or Header  |  1998-12-18  |  73KB  |  2,135 lines

  1. #ifdef INCRCSDATA
  2. static char RCSid[]="$Id: gclient.c,v 1.15 1998/03/22 22:34:21 drd Exp $" ;
  3. #endif
  4.  
  5. /****************************************************************************
  6.  
  7.     PROGRAM: Gnupmdrv
  8.     
  9.     MODULE:  gclient.c
  10.         
  11.     This file contains the client window procedures for Gnupmdrv
  12.     
  13. ****************************************************************************/
  14.  
  15. /* PM driver for GNUPLOT */
  16.  
  17. /*[
  18.  * Copyright 1992, 1993, 1998   Roger Fearick
  19.  *
  20.  * Permission to use, copy, and distribute this software and its
  21.  * documentation for any purpose with or without fee is hereby granted,
  22.  * provided that the above copyright notice appear in all copies and
  23.  * that both that copyright notice and this permission notice appear
  24.  * in supporting documentation.
  25.  *
  26.  * Permission to modify the software is granted, but not the right to
  27.  * distribute the complete modified source code.  Modifications are to
  28.  * be distributed as patches to the released version.  Permission to
  29.  * distribute binaries produced by compiling modified sources is granted,
  30.  * provided you
  31.  *   1. distribute the corresponding source modifications from the
  32.  *    released version in the form of a patch file along with the binaries,
  33.  *   2. add special version identification to distinguish your version
  34.  *    in addition to the base release version number,
  35.  *   3. provide your name and address as the primary contact for the
  36.  *    support of your modified version, and
  37.  *   4. retain our contact information in regard to use of the base
  38.  *    software.
  39.  * Permission to distribute the released version of the source code along
  40.  * with corresponding source modifications in the form of a patch file is
  41.  * granted with same provisions 2 through 4 for binary distributions.
  42.  *
  43.  * This software is provided "as is" without express or implied warranty
  44.  * to the extent permitted by applicable law.
  45. ]*/
  46.  
  47. /*
  48.  * AUTHOR
  49.  * 
  50.  *   Gnuplot driver for OS/2:  Roger Fearick
  51.  * 
  52.  * Send your comments or suggestions to 
  53.  *  info-gnuplot@dartmouth.edu.
  54.  * This is a mailing list; to join it send a note to 
  55.  *  majordomo@dartmouth.edu.  
  56.  * Send bug reports to
  57.  *  bug-gnuplot@dartmouth.edu.
  58. **/
  59.  
  60. #define INCL_PM
  61. #define INCL_WIN
  62. #define INCL_SPL
  63. #define INCL_SPLDOSPRINT
  64. #define INCL_WINSTDFONT
  65. #define INCL_DOSMEMMGR
  66. #define INCL_DOSPROCESS
  67. #define INCL_DOSERRORS
  68. #define INCL_DOSFILEMGR
  69. #define INCL_DOSNMPIPES
  70. #define INCL_DOSSESMGR
  71. #define INCL_DOSSEMAPHORES
  72. #define INCL_DOSMISC
  73. #define INCL_DOSQUEUES
  74. #define INCL_WINSWITCHLIST
  75. #include <os2.h>
  76. #include <string.h>
  77. #include <stdio.h>
  78. #include <io.h>
  79. #include <fcntl.h>
  80. #include <math.h>
  81. #include <stdlib.h>
  82. #include <unistd.h>
  83. #include <process.h>
  84. #include <signal.h>
  85. #include "gnupmdrv.h"
  86.  
  87. /*==== g l o b a l    d a t a ================================================*/
  88.  
  89. extern char szIPCName[] ;       /* name used in IPC with gnuplot */
  90. extern char szIniFile[256] ;    /* full path of ini file */
  91. extern int  bServer ;
  92. extern int  bPersist ;
  93. extern int  bEnhanced ;
  94.  
  95. /*==== l o c a l    d a t a ==================================================*/
  96.  
  97. static long lLineTypes[7] = { LINETYPE_SOLID,
  98.                               LINETYPE_SHORTDASH,
  99.                               LINETYPE_DOT,
  100.                               LINETYPE_DASHDOT,
  101.                               LINETYPE_LONGDASH,
  102.                               LINETYPE_DOUBLEDOT,
  103.                               LINETYPE_DASHDOUBLEDOT } ;
  104. static long lCols[16] =     { CLR_BLACK,
  105.                               CLR_DARKGRAY,
  106.                               CLR_BLUE,
  107.                               CLR_RED,
  108.                               CLR_GREEN,
  109.                               CLR_CYAN,
  110.                               CLR_PINK,
  111.                               CLR_YELLOW,
  112.                               CLR_DARKBLUE,
  113.                               CLR_DARKRED,
  114.                               CLR_DARKGREEN,
  115.                               CLR_DARKCYAN,
  116.                               CLR_DARKPINK,
  117.                               CLR_BROWN,
  118.                               CLR_PALEGRAY,
  119.                               CLR_WHITE } ;
  120.  
  121. static LONG alColourTable[ 16 ] ;
  122.  
  123. #define   GNUBUF    1024        /* buffer for gnuplot commands */
  124. #define   PIPEBUF   4096        /* size of pipe buffers */
  125. #define   CMDALLOC  4096        /* command buffer allocation increment (ints) */
  126. #define   ENVSIZE   2048        /* size of environment */ 
  127.  
  128. #define   PAUSE_DLG 1           /* pause handled in dialog box */
  129. #define   PAUSE_BTN 2           /* pause handled by menu item */
  130. #define   PAUSE_GNU 3           /* pause handled by Gnuplot */
  131.  
  132. #define   DEFLW     50
  133.  
  134. static ULONG    ppidGnu=0L ;      /* gnuplot pid */
  135. static HPS      hpsScreen ;     /* screen pres. space */
  136. static int      iSeg = 1 ;
  137.  
  138. static HSWITCH hSwitch = 0 ;    /* switching between windows */
  139. static SWCNTRL swGnu ;
  140.  
  141. static BOOL     bLineTypes = FALSE ;    // true if use dashed linetypes
  142. BOOL     bWideLines ;
  143. static BOOL     bColours = TRUE ;
  144. static BOOL     bShellPos = FALSE ;
  145. static BOOL     bPlotPos = FALSE ;
  146. static BOOL     bPopFront = TRUE ;
  147. static BOOL     bNewFont = FALSE ;
  148. static BOOL     bHorz = TRUE ;
  149.  
  150. static ULONG    ulPlotPos[4] ;
  151. static ULONG    ulShellPos[4] ;
  152. static PAUSEDATA pausedata = {sizeof(PAUSEDATA), NULL, NULL} ;
  153. static char     szFontNameSize[FONTBUF] ;
  154. static PRQINFO3 infPrinter = { "" } ;
  155. static QPRINT   qPrintData = { sizeof(QPRINT), 0.0, 0.0, 1.0, 1.0, 0, 
  156.                                "", "", &infPrinter, 0, NULL } ;
  157. //static HEV      semStartSeq ;   /* semaphore to start things in right sequence */
  158. static HEV      semPause ;
  159. static HMTX     semHpsAccess ;
  160. static ULONG    ulPauseReply = 1 ;
  161. static ULONG    ulPauseMode  = PAUSE_DLG ;
  162.  
  163. static HWND     hSysMenu ;
  164.             /* stuff for screen-draw thread control */
  165.             
  166. static BOOL     bExist ; 
  167. //static HEV      semDrawDone ;
  168.  
  169.             /* thread control */
  170.  
  171. static TID     tidDraw, tidSpawn ;
  172.  
  173.             /* font data */
  174.  
  175. static int lSupOffset = 0 ;
  176. static int lSubOffset = 0 ;
  177. static int lBaseSupOffset = 0 ;
  178. static int lBaseSubOffset = 0 ;
  179. static int lCharWidth = 217 ;
  180. static int lCharHeight = 465 ; 
  181.  
  182.  
  183. /*==== f u n c t i o n s =====================================================*/
  184.  
  185. int             DoPrint( HWND ) ;
  186. HBITMAP         CopyToBitmap( HPS ) ; 
  187. HMF             CopyToMetaFile( HPS ) ; 
  188. MRESULT         WmClientCmdProc( HWND , ULONG, MPARAM, MPARAM ) ; 
  189. void            ChangeCheck( HWND, USHORT, USHORT ) ;
  190. BOOL            QueryIni( HAB ) ;
  191. static void     SaveIni( HWND ) ;
  192. static void     ThreadDraw( void* ) ;
  193. static void     DoPaint( HWND, HPS ) ;
  194. static void     Display( HPS ) ;
  195. void            SelectFont( HPS, char * );
  196. void            SwapFont( HPS, char * );
  197. static void     CopyToClipBrd( HWND ) ; 
  198. static void     ReadGnu( void* ) ;
  199. static void     EditLineTypes( HWND, HPS, BOOL ) ;
  200. static void     EditCharCell( HPS, SIZEF* ) ;
  201. static HPS      InitScreenPS( void ) ;
  202. static int      BufRead( HFILE, void*, int, PULONG ) ;
  203. int             GetNewFont( HWND, HPS ) ;
  204. void            SigHandler( int ) ;
  205. void            FontExpand( char * ) ;
  206. static char    *ParseText(HPS, char *, BOOL, char *,
  207.                        int, int, BOOL, BOOL ) ;
  208. static void     CharStringAt(HPS, int, int, int, char *) ;
  209. static int      QueryTextBox( HPS, int, char * ) ; 
  210. static void      LMove( HPS hps, POINTL *p ) ;
  211. static void      LLine( HPS hps, POINTL *p ) ;
  212. static void      LType( int iType ) ;
  213.  
  214. /*==== c o d e ===============================================================*/
  215.  
  216. MRESULT EXPENTRY DisplayClientWndProc(HWND hWnd, ULONG message, MPARAM mp1, MPARAM mp2)
  217. /*
  218. **  Window proc for main window
  219. **  -- passes most stuff to active child window via WmClientCmdProc
  220. **  -- passes DDE messages to DDEProc
  221. */
  222. {
  223.     static BOOL    bSw = FALSE ;
  224.     static BOOL    bFirst = TRUE ; 
  225.     static RECTL   rectlPaint = { 0, 0, 0, 0 } ;
  226.     static int     iPaintCount = 0 ;
  227.     static int     firstcall = 1 ;
  228.     
  229.     switch (message) {
  230.  
  231.         case WM_CREATE:
  232.             {
  233.             HDC     hdcScreen ;
  234.             SIZEL   sizlPage ;
  235.                 // set initial values
  236.             ChangeCheck( hWnd, IDM_LINES_THICK, bWideLines?IDM_LINES_THICK:0 ) ;
  237.             ChangeCheck( hWnd, IDM_LINES_SOLID, bLineTypes?0:IDM_LINES_SOLID ) ;
  238.             ChangeCheck( hWnd, IDM_COLOURS, bColours?IDM_COLOURS:0 ) ;
  239.             ChangeCheck( hWnd, IDM_FRONT, bPopFront?IDM_FRONT:0 ) ;
  240.                 // disable close from system menu (close only from gnuplot)
  241.             hApp = WinQueryWindow( hWnd, QW_PARENT ) ; /* temporary assignment.. */
  242.             hSysMenu = WinWindowFromID( hApp, FID_SYSMENU ) ;
  243.                 // setup semaphores
  244. //            DosCreateEventSem( NULL, &semDrawDone, 0L, 0L ) ;
  245. //            DosCreateEventSem( NULL, &semStartSeq, 0L, 0L ) ;
  246.             DosCreateEventSem( NULL, &semPause, 0L, 0L ) ;
  247.             DosCreateMutexSem( NULL, &semHpsAccess, 0L, 1L ) ;
  248.             bExist = TRUE ;
  249.                 // create a dc and hps to draw on the screen
  250.             hdcScreen = WinOpenWindowDC( hWnd ) ;
  251.             sizlPage.cx = 0 ; sizlPage.cy = 0 ;
  252.             sizlPage.cx = 19500 ; sizlPage.cy = 12500 ;
  253.             hpsScreen = GpiCreatePS( hab, hdcScreen, &sizlPage,
  254.                            PU_HIMETRIC|GPIT_NORMAL|GPIA_ASSOC) ;
  255.                 // spawn server for GNUPLOT ...
  256.             tidSpawn = _beginthread( ReadGnu, NULL, 32768, NULL ) ;
  257.             }
  258.             break ;
  259.             
  260.         case WM_GPSTART:
  261.  
  262.                 // get details of command-line window
  263.             hSwitch = WinQuerySwitchHandle( 0, ppidGnu ) ;
  264.             WinQuerySwitchEntry( hSwitch, &swGnu ) ;
  265.             if( firstcall ) {
  266.                 // set size of this window
  267.             WinSetWindowPos( WinQueryWindow( hWnd, QW_PARENT ), 
  268.                              bPopFront?HWND_TOP:swGnu.hwnd,
  269.                              ulShellPos[0],
  270.                              ulShellPos[1],
  271.                              ulShellPos[2],
  272.                              ulShellPos[3], 
  273.                              bShellPos?(bPopFront?SWP_SIZE|SWP_MOVE|SWP_SHOW|SWP_ACTIVATE
  274.                                                  :SWP_SIZE|SWP_MOVE|SWP_SHOW|SWP_ZORDER)
  275.                                       :(bPopFront?SWP_SHOW|SWP_ACTIVATE:SWP_SHOW|SWP_ZORDER) ) ;
  276.             signal( SIGTERM, SigHandler ) ;
  277.                 firstcall = 0 ;
  278.                 }
  279.             if( !bPopFront ) WinSwitchToProgram( hSwitch ) ;
  280. //            DosPostEventSem( semDrawDone ) ;
  281.             DosReleaseMutexSem( semHpsAccess ) ;
  282.             return 0 ;
  283.             
  284.         case WM_COMMAND:
  285.  
  286.             return WmClientCmdProc( hWnd , message , mp1 , mp2 ) ;
  287.  
  288.         case WM_CHAR:    
  289.                     /* If the user types a command in the driver window,
  290.                        we route it to the gnuplot window and switch that
  291.                        to the front. Doesn't work for full-screen
  292.                        sessions, though (but does switch).  */
  293.             {
  294.             USHORT  usFlag ;
  295.             usFlag = SHORT1FROMMP( mp1 ) ;
  296.             if(  !(usFlag & (KC_KEYUP|KC_ALT|KC_CTRL)) ) {
  297.                 USHORT uc = SHORT1FROMMP( mp2 ) ;
  298.                     HWND hw = WinQueryWindow( swGnu.hwnd, QW_BOTTOM ) ;
  299.                     WinSetFocus( HWND_DESKTOP, hw ) ; 
  300.                 WinSendMsg( hw, message, 
  301.                             MPFROM2SHORT((USHORT)(KC_SCANCODE), 1), 
  302.                             MPFROMSHORT(uc) ) ;
  303.                     WinSwitchToProgram( hSwitch ) ;
  304.                     }
  305.             }
  306.             break ;        
  307.  
  308.         case WM_DESTROY:
  309.  
  310.             if( WinSendMsg( hWnd, WM_USER_PRINT_QBUSY, 0L, 0L ) != 0L ) {
  311.                 WinMessageBox( HWND_DESKTOP,
  312.                                hWnd, 
  313.                                "Still printing - not closed",
  314.                                APP_NAME,
  315.                                0,
  316.                                MB_OK | MB_ICONEXCLAMATION ) ;
  317.                 return 0L ;
  318.                 }
  319.               return (WinDefWindowProc(hWnd, message, mp1, mp2));
  320.  
  321.         case WM_PAINT:
  322.             {
  323.             ULONG ulCount ;
  324.             PID pid; TID tid;
  325.             HPS hps_tmp;
  326.             RECTL rectl_tmp;
  327.               DosQueryMutexSem( semHpsAccess, &pid, &tid, &ulCount ) ;
  328.             if (( ulCount > 0 ) && (tid != tidDraw)) {
  329.                 /* simple repaint while building plot or metafile */
  330.                 /* use temporary PS                   */
  331.               hps_tmp = WinBeginPaint(hWnd,0,&rectl_tmp );
  332.               WinFillRect(hps_tmp,&rectl_tmp,CLR_BACKGROUND);
  333.               WinEndPaint(hps_tmp);
  334.                 /* add dirty rectangle to saved rectangle     */
  335.                 /* to be repainted when PS is available again */
  336.               WinUnionRect(hab,&rectlPaint,&rectl_tmp,&rectlPaint);
  337.                 iPaintCount ++ ;
  338.                 break ;
  339.                 } 
  340.             WinInvalidateRect( hWnd, &rectlPaint, TRUE ) ;
  341.             DoPaint( hWnd, hpsScreen ) ;
  342.             WinSetRectEmpty( hab, &rectlPaint ) ;
  343.             }
  344.             break ;     
  345.  
  346.         case WM_SIZE :
  347.             
  348.             {
  349.             WinInvalidateRect( hWnd, NULL, TRUE ) ;
  350.             }
  351.             break ;
  352.  
  353.         case WM_PRESPARAMCHANGED:
  354.             {        
  355.             char *pp ;
  356.             ULONG ulID ;
  357.             pp = malloc(FONTBUF) ;
  358.             if( WinQueryPresParam( hWnd, 
  359.                                    PP_FONTNAMESIZE, 
  360.                                    0, 
  361.                                    &ulID, 
  362.                                    FONTBUF, 
  363.                                    pp, 
  364.                                    QPF_NOINHERIT ) != 0L ) {
  365.                 strcpy( szFontNameSize, pp ) ;
  366.                 bNewFont = TRUE ;
  367.                 WinInvalidateRect( hWnd, NULL, TRUE ) ;
  368.                 }
  369.             free(pp) ;
  370.             } 
  371.             break ;
  372.             
  373.         case WM_USER_PRINT_BEGIN:
  374.         case WM_USER_PRINT_OK :
  375.         case WM_USER_DEV_ERROR :
  376.         case WM_USER_PRINT_ERROR :
  377.         case WM_USER_PRINT_QBUSY :
  378.  
  379.             return( PrintCmdProc( hWnd, message, mp1, mp2 ) ) ;
  380.  
  381.         case WM_GNUPLOT:
  382.                 // display the plot         
  383.             if( bPopFront )
  384.                 WinSetWindowPos( hwndFrame, HWND_TOP, 0,0,0,0, SWP_ACTIVATE|SWP_ZORDER ) ;
  385.             if( iPaintCount > 0 ) { /* if outstanding paint messages, repaint */
  386.                 WinInvalidateRect( hWnd, &rectlPaint, TRUE ) ;
  387.                 iPaintCount = 0 ;
  388.                 }
  389.             return 0L ;
  390.  
  391.         case WM_PAUSEPLOT:
  392.                 /* put pause message on screen, or enable 'continue' button */
  393.             if( ulPauseMode == PAUSE_DLG ) {
  394.                 pausedata.pszMessage = (char*)mp1 ;
  395.                 WinLoadDlg( HWND_DESKTOP,
  396.                             hWnd,
  397.                             (PFNWP)PauseMsgDlgProc,
  398.                             0L,
  399.                             IDD_PAUSEBOX,
  400.                             &pausedata ) ; 
  401.                 }
  402.             else { 
  403.                 WinEnableMenuItem( WinWindowFromID( 
  404.                                    WinQueryWindow( hWnd, QW_PARENT ), FID_MENU ),
  405.                                    IDM_CONTINUE,
  406.                                    TRUE ) ;            
  407.                 }
  408.             return 0L ;
  409.  
  410.         case WM_PAUSEEND:
  411.             /* resume plotting */
  412.             ulPauseReply = (ULONG) mp1 ;
  413.             DosPostEventSem( semPause ) ;
  414.             return 0L ;
  415.     
  416.     default:         /* Passes it on if unproccessed    */
  417.         return (WinDefWindowProc(hWnd, message, mp1, mp2));
  418.     }
  419.     return (NULL);
  420. }
  421.  
  422. MRESULT WmClientCmdProc(HWND hWnd, ULONG message, MPARAM mp1, MPARAM mp2)
  423. /*
  424. **   Handle client window command (menu) messages
  425. */
  426.     {
  427.     extern HWND hApp ;
  428.     static ulPauseItem = IDM_PAUSEDLG ;
  429.  
  430.     switch( (USHORT) SHORT1FROMMP( mp1 ) ) {
  431.                 
  432.         case IDM_ABOUT :    /* show the 'About' box */
  433.              
  434.             WinDlgBox( HWND_DESKTOP,
  435.                        hWnd , 
  436.                        (PFNWP)About ,
  437.                        0L,
  438.                        ID_ABOUT, 
  439.                        NULL ) ;
  440.             break ;
  441.  
  442.  
  443.         case IDM_GPLOTINF:  /* view gnuplot.inf */
  444.             {
  445.             char path[256] ;
  446.             char *p ;
  447.             strcpy( path, "start view " ) ;
  448.             if( (p=getenv("GNUPLOT")) != NULL ) {
  449.                 strcat( path, p ) ;
  450.                 strcat( path, "/" ) ;
  451.                 }    
  452.             strcat( path, "gnuplot" ) ;
  453.             system( path ) ;
  454.             }
  455.             break ;
  456.             
  457.         case IDM_PRINT :    /* print plot */
  458.  
  459.             if( SetupPrinter( hWnd, &qPrintData ) ) {
  460.                             WinPostMsg( hWnd, 
  461.                             WM_USER_PRINT_BEGIN, 
  462.                             (MPARAM) &qPrintData, 
  463.                             (MPARAM) hpsScreen ) ; 
  464.                             }
  465.             break ;
  466.  
  467.         case IDM_PRINTSETUP :    /* select printer */
  468.  
  469.             WinDlgBox( HWND_DESKTOP,
  470.                        hWnd ,
  471.                        (PFNWP)QPrintersDlgProc,
  472.                        0L,
  473.                        IDD_QUERYPRINT, 
  474.                        qPrintData.szPrinterName ) ;
  475.             break ;
  476.  
  477.         case IDM_LINES_THICK:
  478.                 // change line setting
  479.             bWideLines = !bWideLines ;
  480.             ChangeCheck( hWnd, IDM_LINES_THICK, bWideLines?IDM_LINES_THICK:0 ) ;
  481.             WinInvalidateRect( hWnd, NULL, TRUE ) ;
  482.             break ;
  483.  
  484.         case IDM_LINES_SOLID:
  485.                 // change line setting
  486.             bLineTypes = !bLineTypes ;
  487.             ChangeCheck( hWnd, IDM_LINES_SOLID, bLineTypes?0:IDM_LINES_SOLID ) ;
  488.             EditLineTypes( hWnd, hpsScreen, bLineTypes ) ;
  489.             WinInvalidateRect( hWnd, NULL, TRUE ) ;
  490.             break ;
  491.  
  492.         case IDM_COLOURS:
  493.                 // change colour setting
  494.             bColours = !bColours ;        
  495.             ChangeCheck( hWnd, IDM_COLOURS, bColours?IDM_COLOURS:0 ) ;
  496.             WinInvalidateRect( hWnd, NULL, TRUE ) ;
  497.             break ;
  498.  
  499.         case IDM_FRONT:
  500.                 /* toggle z-order forcing */
  501.             bPopFront = !bPopFront ;        
  502.             ChangeCheck( hWnd, IDM_FRONT, bPopFront?IDM_FRONT:0 ) ;
  503.             break ;
  504.  
  505.         case IDM_FONTS:
  506.         
  507.             if( GetNewFont( hWnd, hpsScreen ) ) {
  508.                 bNewFont = TRUE ;
  509.                 WinInvalidateRect( hWnd, NULL, TRUE ) ;
  510.                 }
  511.             break ;
  512.             
  513.         case IDM_SAVE :
  514.             SaveIni( hWnd ) ;
  515.             break ;
  516.             
  517.         case IDM_COPY :         /* copy to clipboard */
  518.             if( WinOpenClipbrd( hab ) ) {
  519.                 CopyToClipBrd( hWnd ) ; 
  520.                 }
  521.             else {
  522.                 WinMessageBox( HWND_DESKTOP,
  523.                                hWnd, 
  524.                                "Can't open clipboard",
  525.                                APP_NAME,
  526.                                0,
  527.                                MB_OK | MB_ICONEXCLAMATION ) ;
  528.                 }
  529.             break ;
  530.  
  531.         case IDM_CLEARCLIP :         /* clear clipboard */
  532.             if( WinOpenClipbrd( hab ) ) {
  533.                 WinEmptyClipbrd( hab ) ;
  534.                 WinCloseClipbrd( hab ) ;
  535.                 }
  536.             else {
  537.                 WinMessageBox( HWND_DESKTOP,
  538.                                hWnd, 
  539.                                "Can't open clipboard",
  540.                                APP_NAME,
  541.                                0,
  542.                                MB_OK | MB_ICONEXCLAMATION ) ;
  543.                 }
  544.             break ;
  545.  
  546.         case IDM_COMMAND:       /* go back to GNUPLOT command window */
  547.             WinSwitchToProgram( hSwitch ) ;
  548.             break ;
  549.  
  550.         case IDM_CONTINUE:
  551.             WinPostMsg( hWnd, WM_PAUSEEND, (MPARAM)1L, (MPARAM)0L ) ; 
  552.             WinEnableMenuItem( WinWindowFromID( 
  553.                                WinQueryWindow( hWnd, QW_PARENT ), FID_MENU ),
  554.                                IDM_CONTINUE,
  555.                                FALSE ) ;            
  556.             break ;
  557.             
  558.         case IDM_PAUSEGNU:  /* gnuplot handles pause */
  559.             ChangeCheck( hWnd, ulPauseItem, IDM_PAUSEGNU ) ;
  560.             ulPauseItem = IDM_PAUSEGNU ;
  561.             ulPauseMode = PAUSE_GNU ;
  562.             break ;
  563.             
  564.         case IDM_PAUSEDLG:  /* pause message in dlg box */
  565.             ChangeCheck( hWnd, ulPauseItem, IDM_PAUSEDLG ) ;
  566.             ulPauseItem = IDM_PAUSEDLG ;
  567.             ulPauseMode = PAUSE_DLG ;
  568.             break ;
  569.             
  570.         case IDM_PAUSEBTN:  /* pause uses menu button, no message */
  571.             ChangeCheck( hWnd, ulPauseItem, IDM_PAUSEBTN ) ;
  572.             ulPauseItem = IDM_PAUSEBTN ;
  573.             ulPauseMode = PAUSE_BTN ;
  574.             break ;
  575.           
  576.         case IDM_HELPFORHELP:
  577.             WinSendMsg(WinQueryHelpInstance(hWnd),
  578.                        HM_DISPLAY_HELP, 0L, 0L ) ;
  579.             return 0L ;
  580.  
  581.         case IDM_EXTENDEDHELP:
  582.             WinSendMsg(WinQueryHelpInstance(hWnd),
  583.                         HM_EXT_HELP, 0L, 0L);
  584.             return 0L ;
  585.  
  586.         case IDM_KEYSHELP:
  587.             WinSendMsg(WinQueryHelpInstance(hWnd),
  588.                        HM_KEYS_HELP, 0L, 0L);
  589.             return 0L ;
  590.  
  591.         case IDM_HELPINDEX:
  592.             WinSendMsg(WinQueryHelpInstance(hWnd),
  593.                        HM_HELP_INDEX, 0L, 0L);
  594.             return 0L ;
  595.  
  596.         default : 
  597.     
  598.             return WinDefWindowProc( hWnd, message, mp1, mp2 ) ;
  599.  
  600.         }  
  601.     return( NULL ) ;
  602.     }                      
  603.  
  604. void ChangeCheck( HWND hWnd , USHORT wItem1 , USHORT wItem2 )
  605. /*
  606. **  Utility function:
  607. **
  608. **  move check mark from menu item 1 to item 2
  609. */
  610.     {
  611.     HWND hMenu ;
  612.  
  613.     hMenu = WinWindowFromID( WinQueryWindow( hWnd, QW_PARENT ), 
  614.                              FID_MENU ) ;            
  615.     if( wItem1 != 0 )
  616.         WinSendMsg( hMenu,
  617.                     MM_SETITEMATTR,
  618.                     MPFROM2SHORT( wItem1, TRUE ),
  619.                     MPFROM2SHORT( MIA_CHECKED, 0 ) ) ;
  620.     if( wItem2 != 0 )
  621.         WinSendMsg( hMenu,
  622.                     MM_SETITEMATTR,
  623.                     MPFROM2SHORT( wItem2, TRUE ),
  624.                     MPFROM2SHORT( MIA_CHECKED, MIA_CHECKED ) ) ;
  625.     }       
  626.  
  627. static void CopyToClipBrd( HWND hWnd ) 
  628. /*
  629. **  Copy window to clipboard as bitmap.
  630. */
  631.     {
  632.     HAB hab ;
  633.     HBITMAP hbm ;
  634.     HMF     hmf ;
  635.  
  636.     hab = WinQueryAnchorBlock( hWnd ) ;
  637.     WinEmptyClipbrd( hab ) ;
  638.     hbm = CopyToBitmap( hpsScreen ) ; 
  639.     WinSetClipbrdData( hab, (ULONG) hbm, CF_BITMAP, CFI_HANDLE) ;
  640.     hmf = CopyToMetaFile( hpsScreen ) ; 
  641.     WinSetClipbrdData( hab, (ULONG) hmf, CF_METAFILE, CFI_HANDLE) ;
  642.     WinCloseClipbrd( hab ) ;
  643.     }
  644.  
  645. HBITMAP CopyToBitmap( HPS hps ) 
  646. /*
  647. **  Copy ps to a bitmap.
  648. */
  649.     {
  650.     HPS     hpsMem ;
  651.     HWND    hwnd ;
  652.     HAB     hab ;
  653.     PSZ     psz[4] = {NULL,"Display",NULL,NULL} ;
  654.     HDC     hdcMem, hdcScr ;
  655.     SIZEL   sizel ;
  656.     BITMAPINFOHEADER2 bmp ;
  657.     PBITMAPINFO2 pbmi ;
  658.     HBITMAP hbm ;
  659.     BYTE    abBmp[80] ;
  660.     LONG    alData[2] ;
  661.     RECTL   rectl ;
  662.     POINTL  aptl[6] ;
  663.     HMF     hmf ;
  664.  
  665.     hdcScr = GpiQueryDevice( hps ) ;
  666.     hwnd = WinWindowFromDC( hdcScr ) ;
  667.     hab = WinQueryAnchorBlock( hwnd ) ;
  668.     hdcMem = DevOpenDC( hab, 
  669.                         OD_MEMORY, 
  670.                         "*", 
  671.                         4L, 
  672.                         (PDEVOPENDATA) psz, 
  673.                         hdcScr ) ;
  674.     sizel.cx = 0/*GNUPAGE*/ ; sizel.cy = 0/*GNUPAGE*/ ;
  675.     hpsMem = GpiCreatePS( hab, hdcMem, &sizel, PU_PELS|GPIA_ASSOC|GPIT_MICRO ) ;
  676.     GpiQueryDeviceBitmapFormats( hpsMem, 2L, alData ) ;
  677.     WinQueryWindowRect( hwnd, &rectl ) ;
  678.     memset( &bmp, 0, sizeof(bmp) ) ;
  679.     bmp.cbFix = (ULONG) sizeof( bmp ) ;
  680.     bmp.cx = (SHORT) (rectl.xRight-rectl.xLeft) ;
  681.     bmp.cy = (SHORT) (rectl.yTop-rectl.yBottom) ;
  682.     bmp.cPlanes = alData[0] ;
  683.     bmp.cBitCount = alData[1] ;
  684.     hbm = GpiCreateBitmap( hpsMem, &bmp, 0, NULL, NULL ) ;
  685.     GpiSetBitmap( hpsMem, hbm ) ;
  686.     aptl[0].x = 0 ; aptl[0].y = 0 ;
  687.     aptl[1].x = (LONG)bmp.cx ; aptl[1].y = (LONG)bmp.cy ;
  688.     aptl[2].x = 0 ; aptl[2].y = 0 ;
  689.     GpiBitBlt( hpsMem, hps, 3L, aptl, ROP_SRCCOPY, BBO_IGNORE ) ;
  690.     GpiDestroyPS( hpsMem ) ;
  691.     DevCloseDC( hdcMem ) ;
  692.     return hbm ;
  693.     }
  694.  
  695. HMF CopyToMetaFile( HPS hps ) 
  696. /*
  697. **  Copy ps to a mteafile.
  698. */
  699.     {
  700.     HDC hdcMF, hdcOld ;
  701.     HAB hab ;
  702.     HWND hwnd ;    
  703.     PSZ psz[4] = {NULL,"Display",NULL,NULL} ;
  704.     HMF hmf ;
  705.     hdcOld = GpiQueryDevice( hps ) ;
  706.     hwnd = WinWindowFromDC( hdcOld ) ;
  707.     hab = WinQueryAnchorBlock( hwnd ) ;
  708.     hdcMF = DevOpenDC( hab, OD_METAFILE, "*", 4L, psz, hdcOld ) ;
  709.     DosRequestMutexSem( semHpsAccess, (ULONG) SEM_INDEFINITE_WAIT ) ;
  710.     GpiSetDrawingMode( hps, DM_DRAW ) ; 
  711.     GpiAssociate( hps, 0 ) ; 
  712.     GpiAssociate( hps, hdcMF ) ;
  713.     ScalePS( hps ) ;    
  714.     GpiDrawChain( hps ) ;
  715.     GpiAssociate( hps, 0 ) ; 
  716.     GpiAssociate( hps, hdcOld ) ; 
  717.     DosReleaseMutexSem( semHpsAccess ) ;
  718.     hmf = DevCloseDC( hdcMF ) ;
  719.     return hmf ;
  720.     }
  721.  
  722. BOOL QueryIni( HAB hab )
  723. /*
  724. ** Query INI file
  725. */
  726.     {
  727.     BOOL         bPos, bData, bSwp  ;
  728.     ULONG        ulOpts[5] ;
  729.     HINI         hini ;
  730.     ULONG        ulCB ;
  731.     char         *p ;
  732.     static SWP   pauseswp ;
  733.     
  734.             // read gnuplot ini file
  735.  
  736.     hini = PrfOpenProfile( hab, szIniFile ) ;
  737.     ulCB = sizeof( ulShellPos ) ;
  738.     bPos = PrfQueryProfileData( hini, APP_NAME, INISHELLPOS, &ulShellPos, &ulCB ) ;
  739.     ulCB = sizeof( SWP ) ;
  740.     bSwp = PrfQueryProfileData( hini, APP_NAME, INIPAUSEPOS, &pauseswp, &ulCB ) ;
  741.     if( bSwp ) pausedata.pswp = &pauseswp ;
  742.     ulCB = sizeof( ulOpts ) ;
  743.     bData = PrfQueryProfileData( hini, APP_NAME, INIOPTS, &ulOpts, &ulCB ) ;
  744.     if( bData ) {
  745.         bLineTypes = (BOOL)ulOpts[0] ;
  746.         bWideLines = (BOOL)ulOpts[1] ;
  747.         bColours = (BOOL)ulOpts[2] ;
  748.         ulPauseMode = ulOpts[3] ;
  749.         bPopFront = (BOOL)ulOpts[4] ;
  750.         }
  751.     else {
  752.         bLineTypes = FALSE ;  /* default values */
  753.      /*   bWideLines = FALSE ; */
  754.         bColours = TRUE ;
  755.         bPopFront = TRUE ;
  756.         ulPauseMode = 1 ;
  757.         }
  758.     ulCB = 4*sizeof(float) ;
  759.     PrfQueryProfileData( hini, APP_NAME, INIFRAC, &qPrintData.xsize, &ulCB ) ;
  760.     if( PrfQueryProfileSize( hini, APP_NAME, INIPRDRIV, &ulCB ) ) {
  761.         PDRIVDATA pdriv = (PDRIVDATA) malloc( ulCB ) ;
  762.         if( pdriv != NULL ) {
  763.             PrfQueryProfileData( hini, APP_NAME, INIPRDRIV, pdriv, &ulCB ) ;
  764.             qPrintData.pdriv = pdriv ;
  765.             qPrintData.cbpdriv = ulCB ;
  766.             }
  767.         }
  768.     PrfQueryProfileString( hini, APP_NAME, INIPRPR, "", 
  769.                            qPrintData.szPrinterName,
  770.                            (long) sizeof qPrintData.szPrinterName ) ;
  771.     PrfQueryProfileString( hini, APP_NAME, INIFONT, INITIAL_FONT, 
  772.                              szFontNameSize, FONTBUF ) ;
  773.     ulCB = sizeof( ulOpts ) ;
  774.     bData = PrfQueryProfileData( hini, APP_NAME, INICHAR, &ulOpts, &ulCB ) ;
  775.     if( bData ) {
  776.         lCharWidth = ulOpts[0] ;
  777.         lCharHeight = ulOpts[1] ;
  778.         }
  779.     else {
  780.         lCharWidth = 217 ;
  781.         lCharHeight = 465 ;
  782.         }
  783.     PrfCloseProfile( hini ) ;
  784.  
  785.     if( qPrintData.szPrinterName[0] == '\0' ) {
  786.             // get default printer name    
  787.         PrfQueryProfileString( HINI_PROFILE,
  788.                                "PM_SPOOLER",
  789.                                "PRINTER",
  790.                                ";",
  791.                                qPrintData.szPrinterName,
  792.                                (long) sizeof qPrintData.szPrinterName ) ;
  793.         if( (p=strchr( qPrintData.szPrinterName, ';' )) != NULL ) *p = '\0' ;
  794.         }
  795.     bShellPos = bPos ;
  796.     return bPos ;
  797.     }
  798.  
  799. static void SaveIni( HWND hWnd )
  800. /*
  801. ** save data in ini file
  802. */
  803.     {
  804.     SWP     swp ;
  805.     HINI    hini ;
  806.     ULONG   ulOpts[5] ;
  807.     HFILE   hfile ;
  808.     ULONG   ulAct ;
  809.     ERRORID errid ;
  810.     char    achErr[64] ;
  811.     HAB     hab ;
  812.  
  813.     hab = WinQueryAnchorBlock( hWnd ) ;    
  814.     hini = PrfOpenProfile( hab, szIniFile ) ;
  815.     if( hini != NULLHANDLE ) {
  816.         WinQueryWindowPos( hwndFrame, &swp ) ;
  817.         ulPlotPos[0] = swp.x ;
  818.         ulPlotPos[1] = swp.y ;
  819.         ulPlotPos[2] = swp.cx ;
  820.         ulPlotPos[3] = swp.cy ;
  821.         PrfWriteProfileData( hini, APP_NAME, INISHELLPOS, &ulPlotPos, sizeof(ulPlotPos) ) ;
  822.         if( pausedata.pswp != NULL )
  823.             PrfWriteProfileData( hini, APP_NAME, INIPAUSEPOS, 
  824.                                  pausedata.pswp, sizeof(SWP) ) ;
  825.         ulOpts[0] = (ULONG)bLineTypes ;
  826.         ulOpts[1] = (ULONG)bWideLines ; 
  827.         ulOpts[2] = (ULONG)bColours ;
  828.         ulOpts[3] = ulPauseMode ; 
  829.         ulOpts[4] = (ULONG)bPopFront ; 
  830.         PrfWriteProfileData( hini, APP_NAME, INIOPTS, &ulOpts, sizeof(ulOpts) ) ;
  831.         PrfWriteProfileData( hini, APP_NAME, INIFRAC, &qPrintData.xsize, 4*sizeof(float) ) ;
  832.         if( qPrintData.pdriv != NULL )
  833.             PrfWriteProfileData( hini, APP_NAME, INIPRDRIV, qPrintData.pdriv, 
  834.                                  qPrintData.cbpdriv ) ;
  835.         PrfWriteProfileString( hini, APP_NAME, INIPRPR, 
  836.                                qPrintData.szPrinterName[0] == '\0'? NULL:
  837.                                qPrintData.szPrinterName ) ;
  838.         PrfWriteProfileString( hini, APP_NAME, INIFONT, szFontNameSize ) ;
  839.         ulOpts[0] = (ULONG)lCharWidth ;
  840.         ulOpts[1] = (ULONG)lCharHeight ;
  841.         PrfWriteProfileData( hini, APP_NAME, INICHAR, &ulOpts, sizeof(ulOpts) ) ;
  842.         PrfCloseProfile( hini ) ;
  843.         }
  844.     else {
  845.         WinMessageBox( HWND_DESKTOP,
  846.                        HWND_DESKTOP,
  847.                        "Can't write ini file",
  848.                        APP_NAME,
  849.                        0,
  850.                        MB_OK | MB_ICONEXCLAMATION ) ;
  851.         }    
  852.     }
  853.  
  854. static void DoPaint( HWND hWnd, HPS hps  ) 
  855. /*
  856. **  Paint the screen with current data 
  857. */
  858.     {
  859.     ULONG ulCount ;
  860.  
  861.     static RECTL rectl ;    
  862.     if( tidDraw != 0 ) {
  863.             /* already drawing - stop it; include the rectl now
  864.                being drawn in, in the update region; and return
  865.                without calling beginpaint so that the paint 
  866.                message is resent */
  867.         GpiSetStopDraw( hpsScreen, SDW_ON ) ;
  868.         DosSleep(1) ;
  869.         WinInvalidateRect( hWnd, &rectl, TRUE ) ;
  870.         return ;
  871.         }
  872.             /* winbeginpaint here, so paint message is
  873.                not resent when we return, then spawn a 
  874.                thread to do the drawing */
  875.     WinBeginPaint( hWnd, hps, &rectl ) ;                 //rl
  876.     tidDraw = _beginthread( ThreadDraw, NULL, 32768, NULL ) ;
  877.     }
  878.  
  879. static void ThreadDraw( void* arg )
  880. /*
  881. **  Thread to draw plot on screen
  882. */
  883.     {
  884.     HAB     hab ;
  885.  
  886.     hab = WinInitialize( 0 ) ;
  887.  
  888.     InitScreenPS() ;        
  889.  
  890.     DosRequestMutexSem( semHpsAccess, (ULONG) SEM_INDEFINITE_WAIT ) ;
  891.     ScalePS( hpsScreen ) ;
  892.     GpiSetStopDraw( hpsScreen, SDW_OFF ) ;  
  893.     GpiSetDrawingMode( hpsScreen, DM_DRAW ) ;
  894.     GpiDrawChain( hpsScreen ) ;
  895.     WinEndPaint( hpsScreen ) ;
  896.     DosReleaseMutexSem( semHpsAccess ) ;
  897.     WinTerminate( hab ) ;
  898.     tidDraw = 0 ;
  899.     }
  900.  
  901. HPS InitScreenPS()
  902. /*
  903. ** Initialise the screen ps for drawing
  904. */
  905.     {
  906.     RECTL   rectClient ;
  907.     int     nColour = 0 ;        
  908.  
  909.     GpiResetPS( hpsScreen, GRES_ATTRS ) ;
  910.     GpiErase(hpsScreen);
  911.  
  912.     WinQueryWindowRect( hApp, (PRECTL)&rectClient ) ;
  913.     {
  914.     double ratio = 1.560 ;
  915.     double xs = rectClient.xRight - rectClient.xLeft ;
  916.     double ys = rectClient.yTop - rectClient.yBottom ;
  917.     if( ys > xs/ratio ) { /* reduce ys to fit */
  918.         rectClient.yTop = rectClient.yBottom + (int)(xs/ratio) ; 
  919.         }
  920.     else if( ys < xs/ratio ) { /* reduce xs to fit */
  921.         rectClient.xRight = rectClient.xLeft + (int)(ys*ratio) ;
  922.         }
  923.     }
  924.        
  925.     GpiSetPageViewport( hpsScreen, &rectClient ) ;
  926.     if( !bColours ) {
  927.         int i ;
  928.         for( i=0; i<8; i++ ) alColourTable[i] = 0 ;
  929.         for( i=8; i<16; i++ ) alColourTable[i] = 0 ;
  930.         alColourTable[0] = 0xFFFFFF ;
  931.         nColour = 16 ;
  932.         }
  933.     GpiCreateLogColorTable( hpsScreen,
  934.                             LCOL_RESET,
  935.                             LCOLF_CONSECRGB,
  936.                             0, nColour, alColourTable ) ;
  937.     return hpsScreen ;
  938.     }
  939.  
  940. enum JUSTIFY { LEFT, CENTRE, RIGHT } jmode;
  941.  
  942.  
  943. short ScalePS( HPS hps )
  944. /*
  945. **  Get a font to use
  946. **  Scale the plot area to world coords for subsequent plotting
  947. */
  948.     {
  949.     RECTL rectView ;
  950.         
  951.     SelectFont( hps, szFontNameSize ) ;
  952.     return 0 ;
  953.     }
  954.  
  955. static SIZEF sizBaseSubSup ;
  956. static SIZEF sizCurSubSup ;
  957. static SIZEF sizCurFont ;
  958. static long lVOffset = 0 ;
  959. static SIZEF sizBaseFont ;
  960. static struct _ft {
  961.     char *name ;
  962.     LONG  lcid ; 
  963.     } tabFont[256] = {{NULL,0L}, {NULL}};
  964.     
  965. void SelectFont( HPS hps, char *szFontNameSize )
  966. /*
  967. **  Select a named and sized outline (adobe) font
  968. */
  969.     {
  970.      HDC    hdc ;
  971.      FATTRS  fat ;
  972.      LONG   xDeviceRes, yDeviceRes ;
  973.      POINTL ptlFont ;
  974.      SIZEF  sizfx ;
  975.      static LONG lcid = 0L ;
  976.      static char *szFontName ;
  977.      static short shPointSize ;
  978.  
  979.      sscanf( szFontNameSize, "%hd", &shPointSize ) ;
  980.      szFontName = strchr( szFontNameSize, '.' ) + 1 ;
  981.  
  982.      fat.usRecordLength  = sizeof fat ;
  983.      fat.fsSelection     = 0 ;
  984.      fat.lMatch          = 0 ;
  985.      fat.idRegistry      = 0 ;
  986.      fat.usCodePage      = 0 ; //GpiQueryCp (hps) ;
  987.      fat.lMaxBaselineExt = 0 ;
  988.      fat.lAveCharWidth   = 0 ;
  989.      fat.fsType          = 0 ;
  990.      fat.fsFontUse       = FATTR_FONTUSE_OUTLINE |
  991.                            FATTR_FONTUSE_TRANSFORMABLE ;
  992.  
  993.      strcpy (fat.szFacename, szFontName) ;
  994.  
  995.      if(tabFont[0].name !=NULL) free( tabFont[0].name ) ;
  996.      tabFont[0].name = strdup( szFontName ) ;
  997.      tabFont[0].lcid = 10L ;
  998.      
  999.      lcid = GpiQueryCharSet( hps ) ;
  1000.      if( lcid != 10L ) lcid = 10L ;
  1001.      else {
  1002.         GpiSetCharSet( hps, 0L) ;
  1003.         GpiDeleteSetId( hps, lcid ) ;
  1004.         }
  1005.      GpiCreateLogFont (hps, NULL, lcid, &fat) ;
  1006.      GpiSetCharSet( hps, lcid ) ;
  1007.  
  1008.      hdc = GpiQueryDevice (hps) ;
  1009.  
  1010.      DevQueryCaps (hdc, CAPS_HORIZONTAL_RESOLUTION, 1L, &xDeviceRes) ;
  1011.      DevQueryCaps (hdc, CAPS_VERTICAL_RESOLUTION,   1L, &yDeviceRes) ;
  1012.  
  1013.                          // Find desired font size in pixels
  1014.  
  1015.      ptlFont.x = 2540L * (long)shPointSize / 72L ;
  1016.      ptlFont.y = 2540L * (long)shPointSize / 72L ;
  1017.  
  1018.                          // Set the character box
  1019.  
  1020.      sizfx.cx = MAKEFIXED (ptlFont.x, 0) ;
  1021.      sizfx.cy = MAKEFIXED (ptlFont.y, 0) ;
  1022.      lVOffset = ptlFont.y ;
  1023.  
  1024.      sizBaseFont = sizfx ;
  1025.      GpiSetCharBox (hps, &sizfx) ;
  1026.  
  1027.                         // set up some useful globals
  1028.      {
  1029.      FONTMETRICS fm ;
  1030.      GpiQueryFontMetrics( hps, sizeof(FONTMETRICS), &fm ) ;
  1031.      lBaseSubOffset = -fm.lSubscriptYOffset ;
  1032.      lBaseSupOffset = fm.lSuperscriptYOffset ;
  1033.      lSubOffset = lBaseSubOffset ;
  1034.      lSupOffset = lBaseSupOffset ;
  1035.      lCharHeight = fm.lMaxAscender*1.2 ;
  1036.      lCharWidth  = fm.lAveCharWidth ;
  1037.      sizBaseSubSup.cx = MAKEFIXED( ptlFont.x*0.7, 0 ) ; 
  1038.      sizBaseSubSup.cy = MAKEFIXED( ptlFont.y*0.7, 0 ) ; 
  1039.      }
  1040.      sizCurFont = sizBaseFont ;
  1041.      sizCurSubSup = sizBaseSubSup ;
  1042.     if( bNewFont ) {
  1043. //        EditCharCell( hps, &sizfx ) ;
  1044.         bNewFont = FALSE ;
  1045.         }
  1046.     }
  1047.  
  1048. void SwapFont( HPS hps, char *szFNS )
  1049. /*
  1050. **  Select a named and sized outline (adobe) font
  1051. */
  1052.     {
  1053.      HDC    hdc ;
  1054.      FATTRS  fat ;
  1055.      LONG   xDeviceRes, yDeviceRes ;
  1056.      POINTL ptlFont ;
  1057.      SIZEF  sizfx ;
  1058.      static LONG lcid = 0L ;
  1059.      static int itab = 1 ;
  1060.      static char *szFontName ;
  1061.      static short shPointSize ;
  1062.  
  1063.      if( szFNS == NULL ) {    /* restore base font */
  1064.          sizCurFont = sizBaseFont ;
  1065.          sizCurSubSup = sizBaseSubSup ;
  1066.          lSubOffset = lBaseSubOffset ;
  1067.          lSupOffset = lBaseSupOffset ;
  1068.          GpiSetCharSet( hps, 10 ) ;
  1069.          GpiSetCharBox (hps, &sizBaseFont) ;
  1070.         }
  1071.      else {
  1072.         sscanf( szFNS, "%hd", &shPointSize ) ;
  1073.         szFontName = strchr( szFNS, '.' ) + 1 ;
  1074.  
  1075.         {
  1076.             int i ;
  1077.             lcid = 0 ;
  1078.             for(i=0;i<itab;i++) {
  1079.                 if( strcmp( szFontName, tabFont[i].name ) == 0 ) {
  1080.                     lcid = tabFont[i].lcid ;
  1081.                     break ;
  1082.                     }
  1083.                 }
  1084.         }
  1085.         if( lcid == 0 ) {   
  1086.  
  1087.         fat.usRecordLength  = sizeof fat ;
  1088.         fat.fsSelection     = 0 ;
  1089.         fat.lMatch          = 0 ;
  1090.         fat.idRegistry      = 0 ;
  1091.         fat.usCodePage      = 0 ; //GpiQueryCp (hps) ;
  1092.         fat.lMaxBaselineExt = 0 ;
  1093.         fat.lAveCharWidth   = 0 ;
  1094.         fat.fsType          = 0 ;
  1095.         fat.fsFontUse       = FATTR_FONTUSE_OUTLINE |
  1096.                                FATTR_FONTUSE_TRANSFORMABLE ;
  1097.  
  1098.         strcpy (fat.szFacename, szFontName) ;
  1099.  
  1100.  
  1101.         tabFont[itab].name = strdup( szFontName ) ;
  1102.         lcid = itab+10 ;
  1103.         tabFont[itab].lcid = lcid ;
  1104.         ++itab ;
  1105.  
  1106. //        lcid = 11L ;
  1107.         GpiSetCharSet( hps, 0L) ;
  1108.         GpiDeleteSetId( hps, lcid ) ;
  1109.         GpiCreateLogFont (hps, NULL, lcid, &fat) ;
  1110.         }
  1111.         GpiSetCharSet( hps, lcid ) ;
  1112.      hdc = GpiQueryDevice (hps) ;
  1113.  
  1114.      DevQueryCaps (hdc, CAPS_HORIZONTAL_RESOLUTION, 1L, &xDeviceRes) ;
  1115.      DevQueryCaps (hdc, CAPS_VERTICAL_RESOLUTION,   1L, &yDeviceRes) ;
  1116.  
  1117.                          // Find desired font size in pixels
  1118.  
  1119.      ptlFont.x = 2540L * (long)shPointSize / 72L ;
  1120.      ptlFont.y = 2540L * (long)shPointSize / 72L ;
  1121.  
  1122.                          // Set the character box
  1123.  
  1124.      sizCurFont.cx = MAKEFIXED (ptlFont.x, 0) ;
  1125.      sizCurFont.cy = MAKEFIXED (ptlFont.y, 0) ;
  1126. //     lVOffset = ptlFont.y ;
  1127.  
  1128.      GpiSetCharBox (hps, &sizCurFont) ;
  1129.      sizCurSubSup.cx = MAKEFIXED( ptlFont.x*0.7, 0 ) ; 
  1130.      sizCurSubSup.cy = MAKEFIXED( ptlFont.y*0.7, 0 ) ; 
  1131.  
  1132.                         // set up some useful globals
  1133.      {
  1134.      FONTMETRICS fm ;
  1135.      GpiQueryFontMetrics( hps, sizeof(FONTMETRICS), &fm ) ;
  1136.      lSubOffset = -fm.lSubscriptYOffset ;
  1137.      lSupOffset = fm.lSuperscriptYOffset ;
  1138.      }
  1139.         }
  1140.         
  1141.      }
  1142.  
  1143. static void ReadGnu( void* arg )
  1144. /*
  1145. ** Thread to read plot commands from  GNUPLOT pm driver.
  1146. ** Opens named pipe, then clears semaphore to allow GNUPLOT driver to proceed.
  1147. ** Reads commands and builds a command list.
  1148. */
  1149.     {
  1150.     HPIPE    hRead = 0L ; 
  1151.     POINTL ptl ;
  1152.     POINTL aptl[4] ;    
  1153.     long lCurCol ;
  1154.     long lOldLine = 0 ;
  1155.     BOOL bBW = FALSE ; /* passed frpm print.c ?? */
  1156.     BOOL bPath = FALSE ;
  1157.     BOOL bDots = FALSE ;
  1158.     char *szEnv ;
  1159.     char *szFileBuf ;
  1160.     ULONG rc; 
  1161.     USHORT usErr ;
  1162.     ULONG cbR ;
  1163.     USHORT i ;
  1164.     PID ppid ;
  1165.     unsigned char buff[2] ;
  1166.     HEV hev ;
  1167.     static char *szPauseText = NULL ;
  1168.     ULONG ulPause ;
  1169.     char *pszPipeName, *pszSemName ;
  1170.     LONG  commands[4] ;
  1171.     HPS hps ;    
  1172.     HAB hab ;
  1173.     int linewidth = DEFLW ;
  1174.  
  1175.     hab = WinInitialize( 0 ) ;
  1176.     DosEnterCritSec() ;
  1177.     pszPipeName = malloc( 256 ) ;
  1178.     pszSemName  = malloc( 256 ) ;
  1179.     DosExitCritSec() ;
  1180.     strcpy( pszPipeName, "\\pipe\\" ) ;
  1181.     strcpy( pszSemName, "\\sem32\\" ) ;
  1182.     strcat( pszPipeName, szIPCName ) ;
  1183.     strcat( pszSemName, szIPCName ) ;
  1184.  
  1185.             /* open a named pipe for communication with gnuplot */
  1186.  
  1187.     rc = DosCreateNPipe( pszPipeName,
  1188.                          &hRead, 
  1189.                          NP_ACCESS_DUPLEX|NP_NOINHERIT|NP_NOWRITEBEHIND ,
  1190.                          1|NP_WAIT|NP_READMODE_MESSAGE|NP_TYPE_MESSAGE,
  1191.                          PIPEBUF,
  1192.                          PIPEBUF,
  1193.                          0xFFFFFFFF) ;
  1194.     hev = 0 ;       /* OK, gnuplot can try to open npipe ... */
  1195.     DosOpenEventSem( pszSemName, &hev ) ;
  1196.     DosPostEventSem( hev ) ;
  1197.     
  1198.  
  1199.     
  1200.         /* attach to gnuplot */
  1201.  
  1202. server:
  1203.  
  1204.     if( DosConnectNPipe( hRead ) == 0L ) {
  1205.  
  1206.         WinPostMsg( hSysMenu,
  1207.                     MM_SETITEMATTR,
  1208.                     MPFROM2SHORT(SC_CLOSE, TRUE ),
  1209.                     MPFROM2SHORT(MIA_DISABLED, MIA_DISABLED) ) ;
  1210.  
  1211.         /* store graphics commands */
  1212.         /* use semaphore to prevent problems with drawing while reallocating
  1213.            the command buffers */
  1214.  
  1215.         DosRead( hRead, &ppidGnu, 4, &cbR ) ;
  1216. //        DosPostEventSem( semStartSeq ) ;         /* once we've got pidGnu */
  1217.         WinPostMsg( hApp, WM_GPSTART, 0, 0 ) ;
  1218.  
  1219.  
  1220.         hps = hpsScreen ;
  1221.    InitScreenPS() ;
  1222.         while (1) {
  1223.         
  1224.             usErr=BufRead(hRead,buff, 1, &cbR) ;
  1225.             if( usErr != 0 ) break ;
  1226.  
  1227.             switch( *buff ) {
  1228.                 case 'G' :    /* enter graphics mode */
  1229.                     {
  1230.                     ULONG ulCount ;    
  1231.                     
  1232.                     if( tidDraw != 0 ) {
  1233.                       /* already drawing - stop it */
  1234.                         GpiSetStopDraw( hpsScreen, SDW_ON ) ;
  1235.                         while(tidDraw != 0) DosSleep(1) ;
  1236.                         }
  1237.                     /* wait for access to command list and lock it */
  1238. //                    DosWaitEventSem( semDrawDone, SEM_INDEFINITE_WAIT ) ;                    
  1239. //                    DosEnterCritSec() ;
  1240.                     DosRequestMutexSem( semHpsAccess, (ULONG) SEM_INDEFINITE_WAIT ) ;
  1241.                     InitScreenPS() ;
  1242.                     ScalePS( hps ) ;
  1243. //                    DosResetEventSem( semDrawDone, &ulCount ) ;
  1244.                     GpiSetDrawingMode( hps, DM_DRAWANDRETAIN ) ;
  1245.                     for(i=1;i<=iSeg;i++)
  1246.                         GpiDeleteSegment( hps, i ) ;
  1247.                     iSeg = 1 ;
  1248.                     GpiOpenSegment( hps, iSeg ) ;
  1249. //                    DosExitCritSec() ;
  1250.                     GpiSetLineEnd( hps, LINEEND_ROUND ) ;
  1251.                     GpiSetLineWidthGeom( hps, linewidth ) ;
  1252.                     GpiSetCharBox (hps, &sizBaseFont) ;
  1253.                     }
  1254.                     break ;
  1255.                     
  1256.                 case 'Q' :     /* query terminal info */
  1257.                     DosWrite( hRead, &lCharWidth, sizeof(int), &cbR ) ;
  1258.                     DosWrite( hRead, &lCharHeight, sizeof(int), &cbR ) ;
  1259.                     break ;
  1260.  
  1261.                 case 'E' :     /* leave graphics mode (graph completed) */
  1262.                     if( bPath ) {
  1263.                         GpiEndPath( hps ) ;
  1264.                         GpiStrokePath( hps, 1, 0 ) ;
  1265.                         bPath = FALSE ;
  1266.                         }
  1267.                     GpiCloseSegment( hps ) ;
  1268. //                    DosPostEventSem( semDrawDone ) ;
  1269.                     DosReleaseMutexSem( semHpsAccess ) ;
  1270.                     WinPostMsg( hApp, WM_GNUPLOT, 0L, 0L ) ;
  1271.                     break ;
  1272.                     
  1273.                 case 'R' :
  1274.                     /* gnuplot has reset drivers, allow user to kill this */
  1275.                     WinPostMsg( hSysMenu,
  1276.                                 MM_SETITEMATTR,
  1277.                                 MPFROM2SHORT(SC_CLOSE, TRUE ),
  1278.                                 MPFROM2SHORT(MIA_DISABLED, (USHORT)0 ) ) ;
  1279.                     /* if we are keeping us on the screen, wait for new connection */
  1280.                     if( bServer||bPersist ) {
  1281.                         DosDisConnectNPipe( hRead ) ;
  1282.                         goto server ;
  1283.                         }    
  1284.                     break ;
  1285.                 
  1286.                 case 'r' :
  1287.                     /* resume after multiplot */
  1288.                     {
  1289.                     ULONG ulCount ;    
  1290.                     DosRequestMutexSem( semHpsAccess, (ULONG) SEM_INDEFINITE_WAIT ) ;
  1291. //                    DosWaitEventSem( semDrawDone, SEM_INDEFINITE_WAIT ) ;
  1292.                     iSeg++ ;
  1293. //                    DosResetEventSem( semDrawDone, &ulCount ) ;
  1294.                     GpiSetDrawingMode( hps, DM_DRAWANDRETAIN ) ;
  1295.                     GpiOpenSegment( hps, iSeg ) ;
  1296.                     }
  1297.                     break ;
  1298.                     
  1299.                 case 's' :
  1300.                     /* suspend after multiplot */
  1301.                     break ;
  1302.  
  1303.                 case 'M' :   /* move */
  1304.                 case 'V' :   /* draw vector */
  1305.                     if( *buff=='M' ) {
  1306.                         if( bPath ) {
  1307.                             GpiEndPath( hps ) ;
  1308.                             GpiStrokePath( hps, 1, 0 ) ;
  1309.                             bPath = FALSE ;
  1310.                             }
  1311.                         }
  1312.                     else {
  1313.                         if( bWideLines/*bWideLines*/ && !bPath ) {
  1314.                             GpiBeginPath( hps, 1 ) ;
  1315.                             bPath = TRUE ;
  1316.                             }
  1317.                         }
  1318.                     BufRead(hRead,&ptl.x, 2*sizeof(int), &cbR) ;
  1319.                     if( (*buff=='V') && bDots ) ptl.x += 5 ;
  1320.                     else if( (*buff=='M') && bDots ) ptl.x -= 5 ;
  1321.                     if( *buff == 'M' ) LMove( hps, &ptl ) ;
  1322.                     else LLine( hps, &ptl ) ;
  1323.                     break ;
  1324.                   
  1325.                 case 'P' :   /* pause */
  1326.                     {
  1327.                     int len ;
  1328.                     BufRead(hRead,&len, sizeof(int), &cbR) ;
  1329.                     len = (len+sizeof(int)-1)/sizeof(int) ;
  1330.                     if( len > 0 ){  /* get pause text */
  1331.                         DosEnterCritSec() ;
  1332.                         szPauseText = malloc( len*sizeof(int) ) ;
  1333.                         DosExitCritSec() ;
  1334.                         BufRead(hRead,szPauseText, len*sizeof(int), &cbR) ;
  1335.                         }
  1336.                     if( ulPauseMode != PAUSE_GNU ) {
  1337.                              /* pause and wait for semaphore to be cleared */
  1338.                         DosResetEventSem( semPause, &ulPause ) ;
  1339.                         WinPostMsg( hApp, WM_PAUSEPLOT, (MPARAM) szPauseText, 0L ) ;
  1340.                         DosWaitEventSem( semPause, SEM_INDEFINITE_WAIT ) ;
  1341.                         }
  1342.                     else { /* gnuplot handles pause */
  1343.                         ulPauseReply = 2 ;
  1344.                         }
  1345.                     DosEnterCritSec() ;
  1346.                     if( szPauseText != NULL ) free( szPauseText ) ;
  1347.                     szPauseText = NULL ;
  1348.                     DosExitCritSec() ;
  1349.                              /* reply to gnuplot so it can continue */
  1350.                     DosWrite( hRead, &ulPauseReply, sizeof(int), &cbR ) ;
  1351.                     }
  1352.                     break ; 
  1353.                        
  1354.                 case 'T' :   /* write text */
  1355.                         /* read x, y, len */
  1356.                     if( bPath ) {
  1357.                         GpiEndPath( hps ) ;
  1358.                         GpiStrokePath( hps, 1, 0 ) ;
  1359.                         bPath = FALSE ;
  1360.                         }
  1361.                     {
  1362.                     int x, y, len, sw ;
  1363.                     char *str ;
  1364.                     BufRead(hRead,&x, sizeof(int), &cbR) ;
  1365.                     BufRead(hRead,&y, sizeof(int), &cbR) ;
  1366.                     BufRead(hRead,&len, sizeof(int), &cbR) ;
  1367.  
  1368.                     DosEnterCritSec() ;
  1369.                     len = (len+sizeof(int)-1)/sizeof(int) ;
  1370.                     if( len == 0 ) len = 1 ; //?? how about read
  1371.                     str = malloc( len*sizeof(int) ) ;
  1372.                     *str = '\0' ;
  1373.                     DosExitCritSec() ;
  1374.                     BufRead(hRead, str, len*sizeof(int), &cbR) ;
  1375.                     lCurCol = GpiQueryColor( hps ) ;
  1376.                     GpiSetColor( hps, CLR_BLACK ) ;
  1377.                     sw = QueryTextBox( hps, strlen(str), str ) ; 
  1378.                     switch(jmode) {
  1379.                     case LEFT:   sw = 0;     break;
  1380.                     case CENTRE: sw = -sw/2; break;
  1381.                     case RIGHT:  sw = -sw;   break;
  1382.                         }
  1383.                     if( bHorz ) {
  1384.                         ptl.x = (LONG)(x+sw) ; ptl.y = (LONG)(y-lVOffset/4) ;
  1385.                         }
  1386.                     else {
  1387.                         ptl.x = (LONG)x ; ptl.y = (LONG)(y+sw) ;
  1388.                         }
  1389.                     if(bEnhanced)
  1390.                         CharStringAt( hps, ptl.x, ptl.y, strlen( str ) , str ) ;
  1391.                     else
  1392.                         GpiCharStringAt( hps, &ptl, strlen( str ), str ) ;
  1393.                     GpiSetColor( hps, lCurCol ) ;
  1394.                     DosEnterCritSec() ;
  1395.                     free(str) ;
  1396.                     DosExitCritSec() ;
  1397.                     }
  1398.                     break ;
  1399.                     
  1400.                 case 'J' :   /* justify */
  1401.                     BufRead(hRead,&jmode, sizeof(int), &cbR) ;
  1402.                     break ;
  1403.  
  1404.                 case 'A' :   /* text angle */
  1405.                     {
  1406.                     int ta ;    
  1407.                     GRADIENTL grdl ;
  1408.                     SIZEF sizHor, sizVer ;
  1409.                     if( bPath ) {
  1410.                         GpiEndPath( hps ) ;
  1411.                         GpiStrokePath( hps, 1, 0 ) ;
  1412.                         bPath = FALSE ;
  1413.                         }
  1414.                     BufRead(hRead,&ta, sizeof(int), &cbR) ;
  1415.                     if( ta == 0 ) {
  1416.                         grdl.x = 0L ; grdl.y = 0L ;
  1417.                         GpiSetCharAngle( hps, &grdl ) ;
  1418.                         if( !bHorz ) {
  1419.                             bHorz = TRUE ;
  1420.                             }
  1421.                         }
  1422.                     else if( ta == 1 ) {
  1423.                         grdl.x = 0L ; grdl.y = 1L ;
  1424.                         GpiSetCharAngle( hps, &grdl ) ;
  1425.                         if( bHorz ) {
  1426.                             bHorz = FALSE ;
  1427.                             }
  1428.                         }
  1429.                     }
  1430.                     break ;
  1431.  
  1432.                 case 'L' :   /* line type */
  1433.                     {
  1434.                     int lt, col ;
  1435.                     if( bPath ) {
  1436.                         GpiEndPath( hps ) ;
  1437.                         GpiStrokePath( hps, 1, 0 ) ;
  1438.                         bPath = FALSE ;
  1439.                         }
  1440.                     BufRead(hRead,<, sizeof(int), &cbR) ;
  1441.                 /* linetype = -2 axes, -1 border, 0 arrows, all to 0 */
  1442.                 col = lt ;
  1443.                     if( lt == -2 )     GpiSetLineWidthGeom( hps, DEFLW*0.85 ) ;
  1444.                     else if( lt == -1 ) GpiSetLineWidthGeom( hps, DEFLW*0.6 ) ;
  1445.                     else GpiSetLineWidthGeom( hps, linewidth ) ;
  1446.                     if( lt < 0 ) lt = 0 ;
  1447.                 lt = (lt%8);
  1448.                 col = (col+2)%16 ;
  1449.                     GpiLabel( hps, lLineTypes[lt] ) ;
  1450. lOldLine=lt ;
  1451.                     LType( (bLineTypes||bBW)?lt:0 ) ;
  1452. //                    GpiSetLineType( hps, (bLineTypes||bBW)?lLineTypes[lt]:lLineTypes[0] ) ;
  1453.                     if( !bBW ) { /* maintain some flexibility here in case we don't want
  1454.                            the model T option */ 
  1455.                         if( bColours ) GpiSetColor( hps, lCols[col] ) ;
  1456.                         else GpiSetColor( hps, CLR_BLACK ) ;
  1457.                         }
  1458.                     }
  1459.                     break ;
  1460.                     
  1461.                 case 'W' :   /* line width */
  1462.                     {
  1463.                     int lw ;
  1464.                     if( bPath ) {
  1465.                         GpiEndPath( hps ) ;
  1466.                         GpiStrokePath( hps, 1, 0 ) ;
  1467.                         bPath = FALSE ;
  1468.                         }
  1469.                     BufRead(hRead,&lw, sizeof(int), &cbR) ;
  1470.                     GpiSetLineWidthGeom( hps, DEFLW*lw/100 ) ;
  1471.                     linewidth = DEFLW*lw/100 ;
  1472.                     }
  1473.                     break ;
  1474.                     
  1475.                  case 'D' :   /* points mode */
  1476.                     {
  1477.                     int lt ;
  1478.                     BufRead(hRead,<, sizeof(int), &cbR) ;
  1479.                       /* 1: enter point mode, 0: exit */
  1480.                     if( bLineTypes || bBW ) {
  1481.                         if( lt==1) LType(0) ;
  1482.                         else LType( lOldLine ) ;
  1483. //                        if( lt == 1 ) lOldLine = GpiSetLineType( hps, lLineTypes[0] ) ;
  1484. //                        else GpiSetLineType( hps, lOldLine ) ;
  1485.                         }
  1486. //                    if( lt == 1 ) GpiSetLineWidthGeom( hps, 20 ) ;
  1487. //                    else GpiSetLineWidthGeom( hps, 50 ) ;
  1488.                     bDots = lt ;
  1489.                     }
  1490.                     break ;
  1491.                 
  1492.                 case 'F' :   /* set font */
  1493.  
  1494.                     {
  1495.                     int len ;
  1496.                     char *str ;
  1497.                     char font[FONTBUF] ;
  1498.                     BufRead(hRead,&len, sizeof(int), &cbR) ;
  1499.                     len = (len+sizeof(int)-1)/sizeof(int) ;
  1500.                     if( len == 0 ) {
  1501.                         SwapFont( hps, NULL ) ;
  1502.                         }
  1503.                     else {
  1504.                         char *p ;
  1505.                         str = malloc( len*sizeof(int) ) ;
  1506.                         BufRead(hRead, str, len*sizeof(int), &cbR) ;
  1507.                         p = strchr(str, ',') ;
  1508.                         if( p==NULL ) strcpy( font, "14" ) ;
  1509.                         else {
  1510.                             *p = '\0' ;
  1511.                             strcpy( font, p+1 ) ;
  1512.                             }
  1513.                         strcat( font,"." ) ;
  1514.                         strcat( font, str ) ;
  1515.                         free( str ) ;
  1516.                         SwapFont( hps, font ) ;
  1517.                         } 
  1518.                     }
  1519.                     break ;
  1520.                     
  1521.                 case 'O' :   /* set options */
  1522.  
  1523.                     {
  1524.                     int len ;
  1525.                     char *str ;
  1526.                     BufRead(hRead,&len, sizeof(int), &cbR) ;
  1527.                     len = (len+sizeof(int)-1)/sizeof(int) ;
  1528.                     bWideLines = FALSE ; /* reset options */
  1529.                     bEnhanced = FALSE ;
  1530.                     
  1531.                     if( len > 0 ) {
  1532.                         char *p ;
  1533.                         p = str = malloc( len*sizeof(int) ) ;
  1534.                         BufRead(hRead, str, len*sizeof(int), &cbR) ;
  1535.                         while( (p=strchr(p,'-')) != NULL ) {
  1536.                             ++p ;
  1537.                             if( *p == 'w' ) bWideLines = TRUE ;
  1538.                             if( *p == 'e' ) bEnhanced = TRUE ;
  1539.                             ++p ;
  1540.                             }
  1541.                         free( str ) ;
  1542.                         } 
  1543.                     }
  1544.                     break ;
  1545.                 
  1546.  
  1547.                  default :  /* should handle error */
  1548.                     break ;
  1549.                  }
  1550.              }
  1551.         }
  1552. exitserver:
  1553.     DosDisConnectNPipe( hRead ) ;
  1554.     WinPostMsg( hApp, WM_CLOSE, 0L, 0L ) ;    
  1555.     }
  1556.  
  1557. static void EditLineTypes( HWND hwnd, HPS hps, BOOL bDashed )
  1558. /*
  1559. */
  1560.     {
  1561.     int i, rc ;
  1562.     char buf[64] ;
  1563.     GpiSetDrawingMode( hps, DM_RETAIN ) ;
  1564.     GpiOpenSegment( hps, iSeg ) ;
  1565.     GpiSetEditMode( hps, SEGEM_REPLACE ) ;
  1566.     for( i=0; i<7; i++ ) {
  1567.         while( GpiSetElementPointerAtLabel( hps, lLineTypes[i] ) ) {
  1568.             GpiOffsetElementPointer( hps, 1 ) ;
  1569.             GpiSetLineType( hps, bDashed?lLineTypes[i]:lLineTypes[0] ) ;
  1570.             }
  1571.         GpiSetElementPointer( hps, 0 ) ;
  1572.         }    
  1573.     GpiSetEditMode( hps, SEGEM_INSERT ) ;
  1574.     GpiCloseSegment( hps ) ;    
  1575.     }
  1576.  
  1577. static void EditCharCell( HPS hps, SIZEF *psize )
  1578. /*
  1579. ** Edit segment to change char cell (font size)
  1580. */
  1581.     {
  1582.     int i ;
  1583.     LONG rl, rc ;
  1584.     SIZEF sizH, sizV ;
  1585.     char buf[64] ;
  1586.     int iVert = 0 ;
  1587.     
  1588.     sizH = *psize ;
  1589.     sizV.cx = sizH.cy ;
  1590.     sizV.cy = sizH.cx ;
  1591.     GpiSetDrawingMode( hps, DM_RETAIN ) ;
  1592.     GpiOpenSegment( hps, iSeg ) ;
  1593.     GpiSetEditMode( hps, SEGEM_REPLACE ) ;
  1594.     i=0 ;
  1595.     while( GpiSetElementPointer( hps, i ) ) {
  1596.         rc = GpiQueryElementPointer( hps) ;
  1597.         if( rc != i ) break ;
  1598.         rl = GpiQueryElementType( hps, &rc, 0, NULL ) ;
  1599.         if( rc == 0x34 || rc == 0x74 ) {
  1600.             LONG gdata ;
  1601.             GpiQueryElement( hps, 5, 4, (PBYTE)&gdata ) ;
  1602.             if( gdata == 0 ) iVert = 0 ;
  1603.             else iVert = 1 ; 
  1604.             }
  1605.         else if( rc==0x33 || rc==0x03 ) GpiSetCharBox(hps, iVert?&sizV:&sizH ) ;
  1606.         ++i ;
  1607.         }
  1608.     GpiSetEditMode( hps, SEGEM_INSERT ) ;
  1609.     GpiCloseSegment( hps ) ;    
  1610.     }
  1611.  
  1612. static int BufRead( HFILE hfile, void *buf, int nBytes, ULONG *pcbR )
  1613. /*
  1614. ** pull next plot command out of buffer read from GNUPLOT
  1615. */
  1616.     {
  1617.     ULONG ulR, ulRR ;
  1618.     int rc ;
  1619.     static char buffer[GNUBUF] ;
  1620.     static char *pbuffer = buffer+GNUBUF, *ebuffer = buffer+GNUBUF ;
  1621.     
  1622.     for( ; nBytes > 0 ; nBytes-- ) {
  1623.         if( pbuffer >= ebuffer ) {
  1624.             ulR = GNUBUF ;
  1625.             rc = DosRead( hfile, buffer, ulR, &ulRR ) ;
  1626.             if( rc != 0 ) return rc ;
  1627.             if( ulRR == 0 ) return 1 ;
  1628.             pbuffer = buffer ;
  1629.             ebuffer = pbuffer+ulRR ;
  1630.             }
  1631.         *(char*)buf++ = *pbuffer++ ;
  1632.         }
  1633.     return 0L ;
  1634.     } 
  1635.  
  1636.  
  1637. int GetNewFont( HWND hwnd, HPS hps ) 
  1638. /*
  1639. ** Get a new font using standard font dialog
  1640. */
  1641.     {
  1642.     static FONTDLG pfdFontdlg;      /* Font dialog info structure */
  1643.     static int i1 =1 ;
  1644.     static int     iSize ;
  1645.     char szPtList[64] ;
  1646.     HWND    hwndFontDlg;     /* Font dialog window handle */
  1647.     char    *p ; 
  1648.     char szFamilyname[FACESIZE];
  1649.  
  1650.     if( i1 ) {
  1651.         strcpy( pfdFontdlg.fAttrs.szFacename, strchr( szFontNameSize, '.' ) + 1 ) ;
  1652.         strcpy( szFamilyname, strchr( szFontNameSize, '.' ) + 1 ) ;
  1653.         sscanf( szFontNameSize, "%d", &iSize ) ;
  1654.         memset(&pfdFontdlg, 0, sizeof(FONTDLG));
  1655.  
  1656.         pfdFontdlg.cbSize = sizeof(FONTDLG);
  1657.         pfdFontdlg.hpsScreen = hps;
  1658.  /*   szFamilyname[0] = 0;*/
  1659.         pfdFontdlg.pszFamilyname = szFamilyname;
  1660.         pfdFontdlg.usFamilyBufLen = FACESIZE;
  1661.         pfdFontdlg.fl = FNTS_HELPBUTTON | 
  1662.                         FNTS_CENTER | FNTS_VECTORONLY | 
  1663.                         FNTS_OWNERDRAWPREVIEW ; 
  1664.         pfdFontdlg.clrFore = CLR_BLACK;
  1665.         pfdFontdlg.clrBack = CLR_WHITE;
  1666.         pfdFontdlg.usWeight = FWEIGHT_NORMAL ; //5 ;
  1667.         pfdFontdlg.fAttrs.usCodePage = 0;
  1668.         pfdFontdlg.fAttrs.usRecordLength = sizeof(FATTRS) ;
  1669.         }
  1670.     sprintf( szPtList, "%d 8 10 12 14 18 24", iSize ) ;
  1671.     pfdFontdlg.pszPtSizeList = szPtList ;
  1672.     pfdFontdlg.fxPointSize = MAKEFIXED(iSize,0); 
  1673.     hwndFontDlg = WinFontDlg(HWND_DESKTOP, hwnd, &pfdFontdlg);
  1674.     if( i1 ) {
  1675.         pfdFontdlg.fl = FNTS_HELPBUTTON | 
  1676.                         FNTS_CENTER | FNTS_VECTORONLY | 
  1677.                         FNTS_INITFROMFATTRS ; 
  1678.         i1=0; 
  1679.         } 
  1680.     if (hwndFontDlg && (pfdFontdlg.lReturn == DID_OK)) {
  1681.         iSize = FIXEDINT( pfdFontdlg.fxPointSize ) ;
  1682.         sprintf( szFontNameSize, "%d.%s", iSize, pfdFontdlg.fAttrs.szFacename ) ;
  1683.         return 1 ;
  1684.         }
  1685.     else return 0 ;
  1686.     }
  1687.  
  1688. void SigHandler( int sig )
  1689. /*
  1690. **  Handle termination signal to free up resources before
  1691. **  termination.
  1692. */
  1693.     {
  1694.     if( sig == SIGTERM ) {
  1695.         if( bPersist ) {
  1696.             DosKillThread( tidSpawn ) ;
  1697.             signal( SIGTERM, SIG_ACK ) ;
  1698.             return ;
  1699.             }
  1700.         DosEnterCritSec() ;
  1701.         DosKillThread( tidSpawn ) ;
  1702.         DosKillThread( tidDraw ) ;
  1703.         DosExitCritSec() ;
  1704.         exit(0) ;
  1705.         }
  1706.     }
  1707.  
  1708. /* disable debugging info */
  1709. #define TEXT_DEBUG(x) /* fprintf x; */
  1710.  
  1711. /* used in determining height of processed text */
  1712.  
  1713. //static float max_height, min_height;
  1714.  
  1715. /* process a bit of string, and return the last character used.
  1716.  * p is start of string
  1717.  * brace is TRUE to keep processing to }, FALSE for do one character
  1718.  * fontname & fontsize are obvious
  1719.  * base is the current baseline
  1720.  * widthflag is TRUE if the width of this should count,
  1721.  *              FALSE for zero width boxes
  1722.  * showflag is TRUE if this should be shown,
  1723.  *             FALSE if it should not be shown (like TeX \phantom)
  1724.  */
  1725.  
  1726. static char *starttext = NULL ;
  1727. static int  textlen = 0 ;
  1728. static BOOL bText = FALSE ;
  1729. static int  textwidth = 0 ;
  1730. static POINTL ptlText ;
  1731. static FILE *ff ;
  1732. static char *ParseText(HPS hps, char *p, BOOL brace, char *fontname,
  1733.                        int fontsize, int base, BOOL widthflag, BOOL showflag)
  1734. {
  1735.     POINTL aptl[TXTBOX_COUNT] ;
  1736.     BOOL bChangeFont = FALSE ;
  1737.     TEXT_DEBUG((ff,"RECURSE WITH [%p] %s, %d %s %.1f %.1f %d %d\n", p, p, brace, fontname, fontsize, base, widthflag, showflag))
  1738.  
  1739.     /* Start each recursion with a clean string */
  1740.  
  1741. //{FILE *ff;int i=textlen;ff=fopen("deb","a");
  1742. //for(i=0;i<textlen;i++)fputc(starttext[i], ff);fputc('\n',ff) ; fclose(ff);}
  1743.         if( textlen > 0 ) {
  1744.             GpiQueryTextBox( hps, textlen, starttext, TXTBOX_COUNT, aptl ) ;
  1745.             if( bHorz ) textwidth += aptl[TXTBOX_BOTTOMRIGHT].x ;
  1746.             else        textwidth += aptl[TXTBOX_BOTTOMRIGHT].y ;
  1747.             }
  1748.         if( bText ) {
  1749.             if(textlen > 0 ) {
  1750.                 GpiCharStringAt( hps, &ptlText, textlen, starttext ) ;
  1751.                 ptlText.x += aptl[TXTBOX_CONCAT].x + (bHorz?0:(-base)) ;
  1752.                 ptlText.y += aptl[TXTBOX_CONCAT].y + (bHorz?base:0) ;
  1753.                 }
  1754.             else {
  1755.                 ptlText.x += (bHorz?0:(-base)) ;
  1756.                 ptlText.y += (bHorz?base:0) ;
  1757.                 }
  1758.             }
  1759.         textlen = 0 ;
  1760.         starttext = p ;
  1761.         if( fontname != NULL ) {
  1762.             char szFont[FONTBUF] ;
  1763.             sprintf(szFont, "%d.%s", fontsize, fontname ) ;
  1764.             SwapFont( hps, szFont ) ;
  1765.             bChangeFont = TRUE ;
  1766.             }
  1767.     if( base != 0 ) GpiSetCharBox( hps, &sizCurSubSup ) ;        
  1768.  
  1769.     for ( ; *p; ++p)
  1770.     {    int shift;
  1771.  
  1772.         switch (*p)
  1773.         {
  1774.             case '}'  :
  1775.                 /*{{{  deal with it*/
  1776.                 if (brace) {
  1777.                     brace = 0 ;
  1778.                     break ;
  1779.                     }
  1780.                 
  1781.                 break;
  1782.                 /*}}}*/
  1783.         
  1784.             case '_'  :
  1785.             case '^'  :
  1786.                 /*{{{  deal with super/sub script*/
  1787.                 
  1788.                 shift = (*p == '^') ? lSupOffset : lSubOffset;
  1789.                 p = ParseText(hps, p+1, FALSE, NULL/*fontname*/, fontsize*0.7, base+shift, widthflag, showflag);                
  1790.                 break;
  1791.                 /*}}}*/
  1792.         
  1793.             case '{'  :
  1794.             {
  1795.                 char *savepos=NULL, save=0;
  1796.                 char *localfontname=fontname, ch;
  1797.                 char localfontbuf[FONTBUF] ;
  1798.                 int recode=1;
  1799.                 int f=fontsize;
  1800.                 BOOL bChangeFont = FALSE ;
  1801.                 char *q=localfontbuf ;
  1802.  
  1803.                 /*{{{  recurse (possibly with a new font) */
  1804.                 
  1805.                 TEXT_DEBUG((ff,"Dealing with {\n"))
  1806.                 
  1807.                 if (*++p == '/')
  1808.                 {    /* then parse a fontname, optional fontsize */
  1809.                     while (*++p == ' ');
  1810.                     if (*p=='-')
  1811.                     {
  1812.                         recode=0;
  1813.                         while (*++p == ' ');
  1814.                     }
  1815.                     localfontname = p;
  1816.                     while ((ch = *p) > ' ' && ch != '=') {
  1817.                             localfontname=localfontbuf ;
  1818.                             if(*p=='_') *q=' ' ;
  1819.                             else *q=*p ;
  1820.                         ++p;++q;
  1821.                         }
  1822.                     *q = '\0' ;
  1823.                     FontExpand( localfontbuf ) ;
  1824.                     save = *(savepos=p);
  1825.                     if (ch == '=')
  1826.                     {
  1827.                         *p++ = '\0';                
  1828.                         /*{{{  get optional font size*/
  1829.                         TEXT_DEBUG((ff,"Calling strtod(%s) ...", p))
  1830.                         f = strtod(p, &p);
  1831.                         TEXT_DEBUG((ff,"Retured %.1f and %s\n", f, p))
  1832.                         
  1833.                         if (!f) f = fontsize;
  1834.                         
  1835.                         TEXT_DEBUG((ff,"Font size %.1f\n", f))
  1836.                         /*}}}*/
  1837.                     }
  1838.                     else
  1839.                     {
  1840.                         *p++ = '\0';
  1841.                         f = fontsize;
  1842.                     }                
  1843.                 
  1844.                     while (*p == ' ')
  1845.                         ++p;
  1846.                     if (! (*localfontname)) {
  1847.                         localfontname = fontname;
  1848.                         if( f != fontsize ) 
  1849.                             localfontname = strchr( szFontNameSize, '.' ) + 1 ;
  1850.                         }
  1851.                 }
  1852.                 /*}}}*/
  1853.                 
  1854.                 TEXT_DEBUG((ff,"Before recursing, we are at [%p] %s\n", p, p))
  1855.         
  1856.                 p = ParseText(hps,p, TRUE, localfontname, f, base, widthflag, showflag);
  1857.                 
  1858.                 TEXT_DEBUG((ff,"BACK WITH %s\n", p));
  1859.                 if (savepos)
  1860.                     /* restore overwritten character */
  1861.                     *savepos = save;
  1862.         
  1863.                 break;
  1864.             }
  1865.                 
  1866.             case '@' :
  1867.                 /*{{{  phantom box - prints next 'char', then restores currentpoint */
  1868.                 
  1869.                 p = ParseText(hps,++p, FALSE, NULL/*fontname*/, fontsize, base, FALSE, showflag);
  1870.                     
  1871.                 break;
  1872.                 /*}}}*/
  1873.         
  1874.             case '&' :
  1875.                 /*{{{  character skip - skips space equal to length of character(s) */
  1876.                 
  1877.                 p = ParseText(hps,++p, FALSE, NULL/*fontname*/, fontsize, base, widthflag, FALSE);
  1878.                     
  1879.                 break;
  1880.                 /*}}}*/
  1881.  
  1882.             case '\\'  :
  1883.                 {
  1884.                 char buffer[4] ; /* should need only one char.. */
  1885.                 char *q = buffer ;
  1886.                 *q = '\0' ;
  1887.                 ParseText(hps,q, FALSE, NULL, fontsize, base, widthflag, showflag);
  1888.                 /*{{{  is it an escape */
  1889.                 /* special cases */
  1890.                 
  1891.                 if (p[1]=='\\' || p[1]=='{' || p[1]=='}')
  1892.                 {
  1893.                     *q++=p[1] ;
  1894.                     ++p ;
  1895.                 }
  1896. #if 0           
  1897.                 else if (p[1] >= '0' && p[1] <= '7')
  1898.                 {
  1899.                     /* up to 3 octal digits */
  1900.                     int c = 0 ;
  1901.                     c+=p[1];
  1902.                     ++p;
  1903.                     if (p[1] >= '0' && p[1] <= '7')
  1904.                     {
  1905.                         c*=8; c+=p[1];
  1906.                         ++p;
  1907.                         if (p[1] >= '0' && p[1] <= '7')
  1908.                         {
  1909.                             c*=8; c+=p[1];
  1910.                             ++p;
  1911.                         }
  1912.                     }
  1913.                     *q++ = c ;
  1914.                     break;
  1915.                 }
  1916. #endif          
  1917.                 *q = '\0' ;
  1918.                 textlen = 1 ;
  1919.                 starttext=buffer ;
  1920.                 ParseText(hps,q, FALSE, NULL/*fontname*/, fontsize, base, widthflag, showflag);
  1921.                 starttext=p+1 ;
  1922.                 textlen = 0 ;
  1923.                 /*}}}*/
  1924.                 }
  1925.                 break ;
  1926.  
  1927.             default: 
  1928.                 ++textlen ;                               
  1929.     
  1930.             /*}}}*/
  1931.  
  1932.         }
  1933.  
  1934.         /* like TeX, we only do one character in a recursion, unless it's
  1935.          * in braces
  1936.          */
  1937.  
  1938.         if (!brace) break ;
  1939.         }
  1940.         if( textlen > 0 ) {
  1941.             GpiQueryTextBox( hps, textlen, starttext, TXTBOX_COUNT, aptl ) ;
  1942.             if( widthflag ) {
  1943.                 if( bHorz ) textwidth += aptl[TXTBOX_BOTTOMRIGHT].x ;
  1944.                 else        textwidth += aptl[TXTBOX_BOTTOMRIGHT].y ;
  1945.                 }
  1946.             }
  1947.         if( bText ) {
  1948.             if( textlen > 0 ) {
  1949.                 if( showflag)
  1950.                     GpiCharStringAt( hps, &ptlText, textlen, starttext ) ;
  1951.                 if( widthflag ) {
  1952.                     ptlText.x += aptl[TXTBOX_CONCAT].x ;
  1953.                     ptlText.y += aptl[TXTBOX_CONCAT].y ;
  1954.                     }
  1955.                 }
  1956.             if( base != 0 ) {
  1957.                 ptlText.x -= (bHorz?0:(-base)) ;
  1958.                 ptlText.y -= (bHorz?base:0) ;
  1959.                 }
  1960.             }
  1961.         if( bChangeFont ) {
  1962.             SwapFont( hps, NULL ) ;
  1963.             bChangeFont = FALSE ;
  1964.             }
  1965.     if( base != 0 ) GpiSetCharBox( hps, &sizBaseFont ) ;        
  1966.                 
  1967.  
  1968.         textlen = 0 ;
  1969.         starttext = p+1 ;
  1970.     return p;
  1971.  
  1972. static void CharStringAt(HPS hps, int x, int y, int len, char *str)
  1973. {
  1974.     /* flush any pending graphics (all the XShow routines do this...) */
  1975.  
  1976.      char *fontname ;
  1977.      int fontsize ;
  1978.  
  1979.     if (!strlen(str))
  1980.         return;
  1981.  
  1982.     /* set up the globals */
  1983.     
  1984.         ptlText.x = x ;
  1985.         ptlText.y = y ;
  1986.         bText = TRUE ;
  1987.         starttext = NULL ;
  1988.         textlen = 0 ;
  1989.         textwidth = 0 ;
  1990.         sscanf( szFontNameSize, "%d", &fontsize ) ;
  1991.         fontname = strchr( szFontNameSize, '.' ) + 1 ;
  1992.         
  1993.     while (*(str = ParseText(hps, str, TRUE, NULL,
  1994.                      fontsize,
  1995.                      0.0, TRUE, TRUE)));
  1996.  
  1997. }
  1998.  
  1999. static int QueryTextBox( HPS hps, int len, char *str ) 
  2000. {
  2001.      char *fontname ;
  2002.      int fontsize ;
  2003.     if (!strlen(str))
  2004.         return 0 ;
  2005.  
  2006.  
  2007.     /* set up the globals */
  2008.     
  2009.         bText = FALSE ;
  2010.         starttext = NULL ;
  2011.         textlen = 0 ;
  2012.         textwidth = 0 ;
  2013.         sscanf( szFontNameSize, "%d", &fontsize ) ;
  2014.         fontname = strchr( szFontNameSize, '.' ) + 1 ;
  2015.         
  2016.     while (*(str = ParseText(hps, str, TRUE, NULL,
  2017.                      fontsize,
  2018.                      0.0, TRUE, TRUE)));
  2019.  
  2020.     return textwidth ;    
  2021. }
  2022.  
  2023. void FontExpand( char *name )
  2024.     {
  2025.     if     ( strcmp(name,"S")==0 ) strcpy( name, "Symbol Set" ) ;
  2026.     else if( strcmp(name,"H")==0 ) strcpy( name, "Helvetica" ) ;
  2027.     else if( strcmp(name,"T")==0 ) strcpy( name, "Times New Roman" ) ;
  2028.     else if( strcmp(name,"C")==0 ) strcpy( name, "Courier" ) ;
  2029.     }
  2030.  
  2031. /*=======================================*/
  2032. static POINTL pCur ;
  2033. static int iLinebegin = 1 ;
  2034. static int iLtype = 0 ;
  2035. static int iState = 0 ;
  2036. static double togo = 0.0 ;
  2037. static int iPatt[8][9]
  2038.   = {
  2039.     {   0,   0,   0,   0,   0,   0,   0,   0,  0 },
  2040.     { 300, 200,  -1,   0,   0,   0,   0,   0,  0 },
  2041.     { 150, 150,  -1,   0,   0,   0,   0,   0,  0 },
  2042.     { 300, 200, 150, 200,  -1,   0,   0,   0,  0 },
  2043.     { 500, 200,  -1,   0,   0,   0,   0,   0,  0 },
  2044.     { 300, 200, 150, 200, 150, 200,  -1,   0,  0 },
  2045.     { 300, 200, 150, 200, 150, 200, 150, 200, -1 },
  2046.     { 500, 200, 150, 200,  -1,   0,   0,   0,  0 }
  2047.     } ;
  2048.  
  2049. void LMove( HPS hps, POINTL *p )
  2050.     {
  2051.     double ds, dx, dy ;
  2052.     if( iLinebegin ) {
  2053.         pCur = *p ;
  2054.         GpiMove( hps, p ) ;
  2055.         }
  2056.     else if( iLtype == 0 ) GpiMove( hps, p ) ;
  2057.     else {
  2058.         dx = p->x - pCur.x ;
  2059.         dy = p->y - pCur.y ;
  2060.         ds = sqrt( dx*dx + dy*dy ) ;
  2061.         dx /= ds ; dy /= ds ;
  2062.         while( ds > 0.0 ) {
  2063.             if( ds < togo ) {
  2064.                 togo -= ds ;
  2065.                 ds = 0.0 ;
  2066.                 GpiMove( hps, p ) ;
  2067.                 pCur = *p ;
  2068.                 }
  2069.             else {
  2070.                 POINTL pn ;
  2071.                 pn.x = pCur.x + togo * dx ;
  2072.                 pn.y = pCur.y + togo * dy ;
  2073.                 GpiMove( hps, &pn ) ;
  2074.                 pCur = pn ;
  2075.                 ds -= togo ;
  2076.                 iState++ ;
  2077.                 if( iPatt[iLtype][iState] < 0 ) {
  2078.                     togo = iPatt[iLtype][0] ;
  2079.                     iState = 0 ;
  2080.         }
  2081.                 else togo = iPatt[iLtype][iState] ;
  2082.     }
  2083.             }
  2084.         }
  2085.     } 
  2086.  
  2087. void LLine( HPS hps, POINTL *p )
  2088.     {
  2089.     double ds, dx, dy ;
  2090.     if( iLinebegin ) iLinebegin = 0 ;
  2091.  
  2092.     if( iLtype == 0 ) GpiLine( hps, p ) ;
  2093.     else {
  2094.         dx = p->x - pCur.x ;
  2095.         dy = p->y - pCur.y ;
  2096.         ds = sqrt( dx*dx + dy*dy ) ;
  2097.         dx /= ds ; dy /= ds ;
  2098.         while( ds > 0.0 ) {
  2099.             if( ds < togo ) {
  2100.                 togo -= ds ;
  2101.                 ds = 0.0 ;
  2102.                 if( iState&1 ) GpiMove( hps, p ) ;
  2103.                 else GpiLine( hps, p ) ;
  2104.                 pCur = *p ;
  2105.                 }
  2106.             else {
  2107.                 POINTL pn ;
  2108.                 pn.x = pCur.x + togo * dx ;
  2109.                 pn.y = pCur.y + togo * dy ;
  2110.                 if( iState&1 ) GpiMove( hps, &pn ) ;
  2111.                 else GpiLine( hps, &pn ) ;
  2112.                 pCur = pn ;
  2113.                 ds -= togo ;
  2114.                 iState++ ;
  2115.                 if( iPatt[iLtype][iState] < 0 ) {
  2116.                     togo = iPatt[iLtype][0] ;
  2117.                     iState = 0 ;
  2118.                     }
  2119.                 else togo = iPatt[iLtype][iState] ;
  2120.                 }
  2121.             }
  2122.         }
  2123.     } 
  2124.  
  2125. void LType( int iType )
  2126.     {
  2127.     iLinebegin = 1 ;
  2128.     if( iType > 7 ) iType = 0 ;
  2129.     iLtype = iType ;
  2130.     iState = 0 ;
  2131.     togo = iPatt[iLtype][0] ;
  2132.     }
  2133.  
  2134.